(function(_scope){

	_scope.cache = pi.base.extend({
		"$Init":function(_name,_isPermanent){
			this.environment.setName(_name||"PICache_"+Number(new Date));
			this.environment.setIsPermanent(_isPermanent?true:false);
			this.environment.setData({});
			if(this.environment.getIsPermanent()){
				this.environment.setStorageApi( new pi.storage(this.environment.getName()) );
				this.importDOMStorage();
			};
		},
		"append":function(){
			for (var i = 0; i < arguments.length; i++) {
				this.environment.appendItem.call(this.environment, arguments[i]);
			}
			return this.environment.getCount();
		},
		"clear":function(){
			if(this.environment.getIsPermanent()){
				this.environment.getStorageApi().remove();
				for(var name in this.environment.getData())
					this.remove(name);
			}
			this.environment.setData({});
		},
		"importDOMStorage":function(){
			this.environment.setData({});
			var data = eval(this.environment.getStorageApi().get())||null;
			
			if(data){
				this.environment.setIsStored(true);
				this.environment.setMaxSize(data.maxSize);
				for(var i=0; i<data.items.length; i++){
					//var api = new pi.storage(this.convertItemName(data.items[i].name,true));
					var api = new pi.storage(data.items[i].name);
					
					this.environment.appendItem(
						new pi.cache.item(this.convertItemName(data.items[i].name)).environment.setCreationTime(data.items[i].creationTime).environment.setExpirationTime(data.items[i].expirationTime).environment.setExpirationSliding(data.items[i].expirationSliding).environment.setPriority(data.items[i].priority).environment.setStorageApi(api),
						true
					);
				};
			};
			return this;
		},
		"get":function(_name,_callback){
			if(!this.has(_name))return null;
			var item = this.environment.getItem(_name);
			if( item.isExpired() ){
				this.remove(_name);
			}
			
			return item.environment.getData();
		},
		"has":function(_name){
			return this.environment.hasItem.apply(this.environment,arguments);
		},
		"convertItemName":function(_name,_toLocal){
			_name = _name.replace("__"+this.environment.getName()+"__","");
			return (_toLocal?"__"+this.environment.getName()+"__":"")+_name;
		},
		"remove":function(){
			this.environment.removeItem.apply(this.environment,arguments);
			return this.environment.getCount();
		},
		"fixSize":function(){
			if(this.environment.getMaxSize()>-1){
				var overage = this.environment.getCount()-this.environment.getMaxSize();
				if(overage>0){
					for(var name in this.environment.getData()){
						var item = this.environment.getData()[name];
						var priority = item.environment.getPriority();
						if(priority==null||priority==1){
							this.environment.removeItem(name);
							overage--;
						}
						if(overage<1)break;
					}
					if(overage>0){
						for(var name in this.environment.getData()){
							overage--;
							if(overage<1)break;
						}
					}
				}
			}
		},
		"editStorage":function(_pattern,_flag,_replacement,_callback){
			this.environment.getStorageApi().set( 
				(
					this.environment.getStorageApi().get()
					||
					"(function(){ return { 'maxSize':"+this.environment.getMaxSize()+", items:[] } })();"
				).replace( new RegExp(_pattern||"(.*)",_flag||""), _replacement||"" ).replace("items:[,","items:[")
			);
			this.environment.setIsStored(true);
		},
		"set":function(_name,_value){
			if(this.environment.getIsPermanent())
				this.environment.getItem(_name).environment.getStorageApi().set(_value);
			else
				this.environment.getItem(_name).environment.setData(_value);
		},
		"environment":{
			"_storageApi":null, "_count":0, "_data":null, "_isPermanent":false, "_isStored":false, "_maxSize":-1, "_name":"",
			"setCount":function(_value){
				this._setCount( this.getCount()+_value );
				return this._parent_;
			},
			"appendItem":function(_item,_bind){
				var item = _item, name = item.environment.getName();
				
				if( this.getData()[name] ){
					if( !this.getData()[name].isExpired() )
						throw Error("The '{0}' Is Key Already Existing In Data.".format(name));
				};
				this.setCount(1);
				this._parent_.fixSize();
				this.removeItem(name);
				this.getData()[name] = item;
				if(this.getIsPermanent()){
					if(!_bind){
						var api = new pi.storage(this._parent_.convertItemName(name,true)).set( item.environment.getData() );
						console.log( api.get() );
						item.environment.setStorageApi( api );
						this._parent_.editStorage("items\:\\[(.*)\\]","","items:[$1,{ name:'{0}', creationTime:{1}, expirationTime:{2}, expirationSliding:{3}, priority:{4} }]".format(
							item.environment.getName(), item.environment.getCreationTime(), item.environment.getExpirationTime(), 
							item.environment.getExpirationSliding(), item.environment.getPriority()
						));
					}
				}
			},
			"getItem":function(_name){
				return this.getData()[_name];
			},
			"hasItem":function(_name){
				var item = this.getItem(_name);
				return Boolean(item)?!item.isExpired():false;
			},
			"removeItem":function(_name){
				if(!this.hasItem(_name))return;
				this.setCount(-1);
				if (this.getIsPermanent()) {
					this.getItem(_name).environment.getStorageApi().remove();
				}
				delete this.getItem(_name);
			}
		}
	});
	
	pi.cache.item = pi.base.extend({
 		"$Init":function(_name){
			this.environment.setName(_name||("PICacheItem_"+Number(new Date)));
			this.environment.setCreationTime( Number(new Date) );
			return this;
		},
		"isExpired":function(){
			if( this.environment.getExpirationTime() )
				return this.environment.getExpirationTime()<=Date.now();
			if( this.environment.getExpirationSliding() )
				return ( this.environment.getExpirationSliding()+this.environment.getCreationTime() )<=Number(new Date);
			return false;
		},
		"environment":{
			"_creationTime":0, "_data":"", "_expirationTime":0, "_expirationSliding":0, "_name":"", "_priority":0, "_storageApi":null,
			"getData":function(){
				if(this.getStorageApi()){
					return this.getStorageApi().get()
				}
				return this._getData();
			}
		}
	});

})(pi);